/**
 * 
 */
package com.sunwayhorizo.health.business.clinic.emr.document;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.ejb.Stateless;

import org.jboss.seam.Component;
import org.jboss.seam.annotations.Name;

import com.sunwayhorizo.health.business.base.BaseManager;
import com.sunwayhorizo.health.business.clinic.emr.document.query.DocumentQueryLocal;
import com.sunwayhorizo.health.business.clinic.emr.emrmanager.EmrManagerLocal;
import com.sunwayhorizo.health.business.dto.ResultsDTO;
import com.sunwayhorizo.health.business.dto.clinic.emr.document.EmrWriterDTO;
import com.sunwayhorizo.health.common.DataTypeUtil;
import com.sunwayhorizo.health.common.DateUtil;
import com.sunwayhorizo.health.common.ListUtil;
import com.sunwayhorizo.health.common.StrUtil;
import com.sunwayhorizo.health.hl7.common.Hl7Exception;
import com.sunwayhorizo.health.hl7.datatypes.CS;
import com.sunwayhorizo.health.hl7.datatypes.ED;
import com.sunwayhorizo.health.hl7.rim.ActParticipation;
import com.sunwayhorizo.health.hl7.rim.ActRelationship;
import com.sunwayhorizo.health.hl7.rim.ControlAct;
import com.sunwayhorizo.health.hl7.rim.Document;
import com.sunwayhorizo.health.hl7.rim.Observation;
import com.sunwayhorizo.health.hl7.rim.Role;
import com.sunwayhorizo.health.hl7.vocabulary.ActRelationshipType;
import com.sunwayhorizo.health.hl7.vocabulary.Direction;
import com.sunwayhorizo.health.hl7.vocabulary.ParticipationType;

/**
 * @ClassName InpatientMedicalProcessManager <br>
 * @PackageName com.sunwayhorizo.health.business.clinic.emr.document <br>
 * @Description 病程记录 <br>
 * @Author jinzw <br>
 * @Date 2011-03-16 <br>
 * @Version 1.0 <br>
 * @ModifiedDesc <br>
 * @ModifiedDate <br>
 * @ModifiedBy <br>
 * @Copyright 2010-2020 北京三维海容 All Rights Reserved. <br>
 */
@Stateless
@Name(value = "InpatientMedicalProcessManager")
public class InpatientMedicalProcessManager extends BaseManager implements InpatientMedicalProcessManagerLocal
{

    private DocumentCommonManagerLocal ecm = (DocumentCommonManagerLocal) Component.getInstance("DocumentCommonManager");
    private InpatientRecordsManagerLocal inpRecManager = (InpatientRecordsManagerLocal) Component.getInstance("InpatientRecordsManager");
    private DocumentQueryLocal documentQuery = (DocumentQueryLocal) Component.getInstance("DocumentQuery");
    
    public ResultsDTO newFirstCourse(EmrWriterDTO emr) throws Hl7Exception
    {
        Document doc = null;
        //得到患者病历管理动作
//        EmrManagerLocal emrManer =(EmrManagerLocal)Component.getInstance("EmrManager");
//        Document document= emrManer.findEmrManagerByPatientId(emr.getPatientRoleId(), emr.getPatientNum());
        //该病历可以进行书写 
//        if(null != document && (!document.getStatusCode().code().toString().equals("5") || !document.getStatusCode().code().toString().equals("6"))) 
//        {
            if (StrUtil.isEmpty(emr.getId()))
            {
                return inpRecManager.newDocument(emr);
            }
            else
            {
                //得到首次病程动作
                doc = baseQuery.findDocumentById(emr.getId());
                // 设置签名信息
                if (!emr.getSignature().equals("0") || !emr.getSignature().equals("1"))
                {
                    ecm.setSignatureInfo(emr, doc); 
                }
                // 保存病历文件
                if (null != emr.getContents())
                {
                    ED text = DataTypeUtil.getED(null, emr.getContents());
                    doc.setText(text);
                }
                if (ListUtil.isNotEmpty(emr.getEmrDiagnosisList()))
                {
                    ecm.setRelationship(doc, emr); // 设置动作关连
                }
                update(doc);
                log.info("电子病历首次病程签名成功");
                return getResultsDTO("电子病历首次病程签名成功", true, doc.getActId());
            }
//        }
//        else
//        {
//            return getResultsDTO("该患者病历已经关闭，不能在进行书写", true, null);
//        }
       
    }


    public ResultsDTO newInpMedPro(EmrWriterDTO emr) throws Hl7Exception
    {
        if ((null == emr) || (null == emr.getRimRoleEmrWriterClassId()) || (null == emr.getClassCode()))
        {
            log.info("新增病程失败，数据为空");
            return getResultsDTO("新增病程失败，数据为空", false, null);
        }
        Document doc = null;
        //得到患者病历管理动作
//        EmrManagerLocal emrManer =(EmrManagerLocal)Component.getInstance("EmrManager");
//        Document document= emrManer.findEmrManagerByPatientId(emr.getPatientRoleId(), emr.getPatientNum());
        //该病历可以进行书写 
//        if(null != document && (!document.getStatusCode().code().toString().equals("5") || !document.getStatusCode().code().toString().equals("6"))) 
//        {
            // 创建病程动作
            String code = emr.getClassCode();
            doc = ecm.creatClinicalDocument(code);
            
            // 给病程动作赋值
            doc = ecm.injectDtoToDocNotFile(emr, doc); 
            
            //得到所有参与到病程动作的角色
            Map<CS,Role> socopeMap = ecm.findWriteEmrParticiRole(emr);
            //构建Participation列表
            constructParticipationList(socopeMap,emr);
            
            //得到诊断动作集合
            List<Observation> obsList = null;
            if (ListUtil.isNotEmpty(emr.getEmrDiagnosisList()))
            {
                obsList = ecm.findObservationList(emr);
            }
            //把所有的动作加入到List列表中，为与病历书写动作建立关系做准备
            if(ListUtil.isNotEmpty(obsList))
            {
                for(Observation obs : obsList)
                {
                    ActRelationship relat = getActFactory().newActRelationship();
                    relat.setTypeCode(ActRelationshipType.DIAG);
                    addRelationship(obs, relat, Direction.SOURCE);
                }
            }
            
//            //书写跟病历管理建立关系
//            ActRelationship relat = getActFactory().newActRelationship();
//            relat.setTypeCode(ActRelationshipType.PRCN);
//            addRelationship(document, relat, Direction.SOURCE);
            
            // 创建ControlAct
            ControlAct control = newControlAct(doc); 
            
            //持久化ControlAct
            save(control);
            
            // 单独保存病程内容
            addSelectFile(emr);

            log.info("新增病程记录成功" + doc.getActId().toString());
//        }
//        else
//        {
//            return getResultsDTO("该患者病历已经关闭，不能在进行书写", true, null);
//        }
       
        return getResultsDTO("新增病程记录成功", true, doc.getActId().toString());
    }


    /**
     * 添加病程记录到首程文件中
     * 
     * @param emr
     *            病程记录信息
     * @throws Hl7Exception
     */
    @SuppressWarnings("rawtypes")
    public void addSelectFile(EmrWriterDTO emr) throws Hl7Exception
    {
        List list = documentQuery.findFirstMedicalActIdByPatientId(emr.getPatientRoleId(),emr.getPatientNum());
        Long actId = 0l;
        if (ListUtil.isNotEmpty(list))
        {
            actId = (Long) list.get(0);
        }
        if (actId == 0)
        {
            log.info("病程内容保存失败");
            return;
        }
        Document doc = baseQuery.findDocumentById(String.valueOf(actId));
        // 病历内容
        byte[] contents = emr.getContents();
        if (null != contents)
        {
            // 如果内容不为空
            ED desc = DataTypeUtil.getED("", contents);
            doc.setText(desc);
        }
        em.merge(doc);
        log.info("更新病历文件成功，动作id="+doc.getActId());
    }

    public ResultsDTO medProcessSignature(EmrWriterDTO emr) throws Hl7Exception
    {
        // 保存并签名
        if (StrUtil.isEmpty(emr.getId()))
        {
            return newInpMedPro(emr);
        }
        else
        {
            Document doc = baseQuery.findDocumentById(emr.getId());
            // 设置签名信息
            ecm.setSignatureInfo(emr, doc);
            addSelectFile(emr);// 保存病程内容
            //修改宏元素
            ecm.modifyMacro(doc,emr.getMacroContents());
            // 设置动作关连
            if (ListUtil.isNotEmpty(emr.getEmrDiagnosisList()))
            {
                ecm.setRelationship(doc, emr);
            }
            em.merge(doc);
          
            log.info("电子病历病程签名成功");
            return getResultsDTO("电子病历病程签名成功", true, doc.getActId());
        }
    }

    public ResultsDTO updateMedEmr(EmrWriterDTO emr) throws Hl7Exception
    {
        if ((null == emr) || (StrUtil.isEmpty(emr.getId())))
        {
            log.info("更新电子病历失败，EmrWriterDTO数据为空");
            return getResultsDTO("更新电子病历失败，病程信息为空", false, null);
        }
        Document doc = baseQuery.findDocumentById(emr.getId());
        // 保存病程内容
        addSelectFile(emr);
        //修改宏元素
        ecm.modifyMacro(doc,emr.getMacroContents());
        // 设置动作关连
        if (ListUtil.isNotEmpty(emr.getEmrDiagnosisList()))
        {
            ecm.setRelationship(doc, emr);
        }
        em.merge(doc);
       
        log.info("更新电子病历成功");
        return getResultsDTO("更新电子病历成功", true, null);
    }


    @SuppressWarnings("rawtypes")
    public ResultsDTO delEmr(List ids) throws Hl7Exception
    {
        if (ListUtil.isEmpty(ids))
        {
            log.info("删除电子病历失败，数据为空");
            return getResultsDTO("删除电子病历失败，数据为空", false, null);
        }
        String rel = ecm.delDoc(ids);
        if ("-1".equals(rel))
        {
            log.info("删除电子病历失败");
            return getResultsDTO("删除电子病历失败", false, null);
        }
        log.info("删除电子病历成功");
        return getResultsDTO("删除电子病历成功", true, null);
    }


    public ResultsDTO delInpatientMedicalProcess(EmrWriterDTO emrDto) throws Hl7Exception
    {
        if (StrUtil.isEmail(emrDto.getId()))
            return getResultsDTO("删除电子病历失败，病程记录没有选中", true, null);
        String actId = emrDto.getId();
        Document doc = baseQuery.findDocumentById(actId);
        em.remove(doc);
        addSelectFile(emrDto);
        return getResultsDTO("删除电子病历成功", true, null);
    }
    
    private void constructParticipationList(Map<CS,Role> socopeMap,EmrWriterDTO emr) throws Hl7Exception
    {
        if(!socopeMap.isEmpty())
        {
            Set<CS> set = socopeMap.keySet();
            for(Iterator<CS> it = set.iterator();it.hasNext();)
            {
                CS typeCode = it.next();
                Role empRole = socopeMap.get(typeCode);
                ActParticipation part = getActFactory().newActParticipation();
                part.setTypeCode(typeCode);
                if(typeCode.equals(ParticipationType.RCT))
                {
                    if (StrUtil.isNotEmpty(emr.getMacroContents()))
                    {
                        // 患者入院记录中单独保存的json字符串
                        ED ed = DataTypeUtil.getED(emr.getMacroContents());
                        part.setNoteText(ed);
                    }
                    //住院次数
                    part.setSequenceNumber(DataTypeUtil.getINT(Long.valueOf(emr.getPatientNum())));
                }
                if(typeCode.equals(ParticipationType.ESC) 
                        || typeCode.equals(ParticipationType.DIS) 
                        || typeCode.equals(ParticipationType.CON))
                {
                    // 医生签名时间
                    part.setCreateTime(DataTypeUtil.getTS(DateUtil.getDate()));
                }
                addParticipation(empRole, part);
            }
        }
    }

}
